#ifndef SOCKET_H
#define SOCKET_H
#include "socket_include.h"


#include <string>

class ISocketHandler;
class Socket {
friend class ISocketHandler;
public:
	/** "Default" constructor */
	Socket(ISocketHandler&);

	virtual ~Socket();

	/** Create a socket file descriptor.
		\param af Address family AF_INET / AF_INET6 / ...
		\param type SOCK_STREAM / SOCK_DGRAM / ...
		\param protocol "tcp" / "udp" / ... */
	SOCKET CreateSocket(int af,int type,const std::string& protocol = "");

	/** Returns reference to sockethandler that owns the socket. 
	If the socket is detached, this is a reference to the slave sockethandler.
	*/
	ISocketHandler& Handler() const;

	virtual bool Open(std::string & serverName, int port){}
	virtual bool Open(const char * serverName, int port){}
	virtual int Close();
	
	/** Set socket non-block operation. */
	bool SetNonblocking(bool);

	/** Set socket non-block operation. */
	bool SetNonblocking(bool, SOCKET);

	/** Return file descriptor assigned to this socket. */
	SOCKET GetSocket() { return m_socket;}

	/** Assign this socket a file descriptor created
	by a call to socket() or otherwise. */
	void Attach(SOCKET s) { m_socket = s;}

	/** Check if SSL is Enabled for this TcpSocket.
	\return true if this is a TcpSocket with SSL enabled */
	bool IsSSL();
	/** Enable SSL operation for a TcpSocket. */
	void EnableSSL(bool x = true);
	/** Still negotiating ssl connection.
		\return true if ssl negotiating is still in progress */
	bool IsSSLNegotiate();
	/** Set flag indicating ssl handshaking still in progress. */
	void SetSSLNegotiate(bool x = true);

	void usingZlibCompression();

	std::istream * getIStream() {return is;}
	std::ostream * getOStream() {return os;}
protected:
	/** default constructor not available */
	Socket() : m_handler(m_handler) {}
	/** copy constructor not available */
	Socket(const Socket& s) : m_handler(s.m_handler) {}

	/** assignment operator not available. */
	Socket& operator=(const Socket& ) { return *this; }
private:
	ISocketHandler& m_handler; ///< Reference of ISocketHandler in control of this socket
	SOCKET m_socket; ///< File descriptor
	ipaddr_t m_host; ///< socks4 server address
	port_t m_port; ///< socks4 server port number
	std::string m_socket_protocol;
	std::istream * is;
	std::ostream * os;

	bool m_b_enable_ssl; ///< Enable SSL for this TcpSocket
	bool m_b_ssl; ///< ssl negotiation mode (TcpSocket)
#ifdef _WIN32
static	WSAInitializer m_winsock_init; ///< Winsock initialization singleton class
#endif

};

#endif //SOCKET_H
